/* thread_pool.c
 * 实现线程池相关的操作
 * */

#include "../include/head.h"
#include "../include/thread_pool.h"

//线程处理函数
void *threadFunc(void *arg){
    pTaskQue_t pQue = (pTaskQue_t)arg;  //接收传进来的参数
    pTaskNode_t pCur = NULL;    //用来接收任务
    int sendRet = 0;
    int getRet = 1;

    while(1){
        //循环等待任务队列
        pthread_mutex_lock(&pQue->mutex);

        if(pQue->exitFlag == 1){
            //如果是退出信号，解锁然后退出
            /* pQue->exited++;  //方法二要用的*/
            printf("child thread exit!\n");
            /* pthread_cond_signal(&pQue->cond2);   //方法二要用的 */
            pthread_mutex_unlock(&pQue->mutex);
            pthread_exit(0);
        }
        if(0 == pQue->size){
            //如果任务队列为空，等待信号
            pthread_cond_wait(&pQue->cond1, &pQue->mutex);//等待条件变量
            //信号来了，判断是否为退出信号
            if(pQue->exitFlag == 1){
                //如果是退出信号，已退出数目加一，解锁然后退出
                /* pQue->exited++;  //方法二要用的 */
                printf("child thread exit!\n");
                /* pthread_cond_signal(&pQue->cond2);   //方法二要用的 */
                pthread_mutex_unlock(&pQue->mutex);
                pthread_exit(0);
            }
        }
        getRet = taskQueGet(pQue, &pCur);
        //获得任务之后，就离开临界区，解锁
        pthread_mutex_unlock(&pQue->mutex);

        if(!getRet){
            //如果成功拿到任务，做任务
            sendRet = zeroCpySend(pCur->clientFd, "file");  //向客户端发送文件
            if(sendRet == -1){
                //客户端中途断开连接
                printf("client exit!\n");
                break;
            }
            printf("file has been sent!\n");
            //释放任务结点
            free(pCur);
            pCur = NULL;
        }
        else{
            printf("child thread exit!\n");
            pthread_exit(0);
        }
    }
    return 0;
}

//初始化线程池
int threadPoolInit(pThreadPool_t pPool, int threadNum){
    pPool->threadNum = threadNum;
    pPool->pthid = (pthread_t*)calloc(threadNum, sizeof(pthread_t));
    taskQueInit(&pPool->tQue);  //调用函数，初始化任务队列
    return 0;
}

//启动线程池
int threadPoolStart(pThreadPool_t pPool){
    //循环创建子线程
   for(int i = 0; i < pPool->threadNum; ++i){
        pthread_create(&pPool->pthid[i], NULL, threadFunc, &pPool->tQue);
    }
    return 0;
}
